<?php
/**
 * Application front controller
 * 
 * @author paq
 *
 */
class Controller_Front extends Controller_Abstract
{	
	/**
	 * 
	 * @var FrontController
	 */
	protected static $_instance;
	
	/**
	 * Controller name parameter name in $_GET
	 * 
	 * @var string
	 */
	const ID_CONTROLLER = 'ctrl';
	
	/**
	 * Action name parameter name in $_GET
	 *  
	 * @var string
	 */
	const ID_ACTION		= 'action';
	
	/**
	 * 
	 * @var string
	 */
	protected $_defaultActionController;
	
	/**
	 * Registered controllers
	 * 
	 * @var array
	 */
	protected $_controllers = array();
	
	/**
	 * Used view templates system
	 * 
	 * @var Smarty
	 */
	protected $_view;
	
	public function __construct()
	{
		parent::__construct('front');
		
		// FIXME: read from db
		$this->_defaultActionController = 'news';
		
		$this->registerHelper(new Controller_Helper_Header($this));
		$this->registerHelper(new Controller_Helper_Menu_Top($this));
		$this->registerHelper(new Controller_Helper_Menu_Right($this));
		
		$this->initView();
	}
	
	/**
	 * Returns the only front controller instance
	 * 
	 * @return FrontController
	 */
	/*public static function get()
	{
		if (!isset(self::$_instance)) {
			self::$_instance = new FrontController();
		}
		
		return self::$_instance;
	}*/
	
	/**
	 * Initializes view system
	 * 
	 * @return void
	 */
	protected function initView()
	{
		Log::info('View initialization');
		try {
			$this->_view = View::get();
		} catch (Exception $e) {
			throw new Exception('View system could not be initialized. ' . $e->getMessage());
		}
	}
	
	/**
	 * Returns used template system object
	 * 
	 * @return Smarty
	 */
	public function view()
	{
		return $this->_view;
	}
	
	/**
	 * Dispatches user request to proper action controller
	 * 
	 * @return void
	 */
	public function dispatch()
	{
		$this->preDispatch();
		
		Log::info('Dispatching front controller');
		
		$controller = strtolower((isset($_GET[self::ID_CONTROLLER])) 
			? $_GET[self::ID_CONTROLLER] : $this->_defaultActionController);
		//$controller .= 'controller';
		$action = strtolower((isset($_GET[self::ID_ACTION])) ? $_GET[self::ID_ACTION] : 'index'); 
		$action .= 'Action';
		
		//var_dump($this->_controllers);
		if (array_key_exists($controller, $this->_controllers)) {
			Log::info('Dispatching request to ' . $controller);
			
			$controller = $this->_controllers[$controller];
			//var_dump($controller);
			try {
				$controller->dispatch();
				$controller->$action();
			} catch (Exception $e) {
				$this->view()->assign('fail_info', $e->getMessage());
				$this->view()->display('fail.tpl');
			}
		} else {
			$msg = $controller . ' controller is not registered for FrontController or allowed.';
			
			$this->view()->assign('fail_info', $msg);
			$this->view()->display('fail.tpl');
			//throw new Exception();
		}
		
		$this->postDispatch();
	}
	
	/**
	 * Pre-dispatch action
	 * Prints header template
	 * 
	 * @return void
	 */
	protected function preDispatch()
	{
		Log::info('preDispatch');
		
		$this->getHelper('header')->run();
		$this->getHelper('topmenu')->run();
		$this->getHelper('rightmenu')->run();
	}
	
	/**
	 * Post-dispatch action
	 * Prints footer and log template
	 * 
	 * @return void
	 */
	protected function postDispatch()
	{
		Log::info('postDispatch');
		
		$this->view()->display('footer.tpl');
		
		$this->logInfo();		
	} 
	
	/**
	 * Show log info
	 * 
	 * @return void
	 */
	protected function logInfo()
	{
		if (isset($_GET['debug'])) {
			$this->view()->assign('log_info', Log::getInfo());
			$this->view()->display('log.tpl');
		}
	}
	
	/**
	 * Registers action controller as available for this front controller
	 * 
	 * @param $controller	action controller wich may be used by this front controller
	 * @return void
	 */
	public function register(Controller_Abstract $controller)
	{
		// FIXME: check if not null
		if (isset($this->_controllers[$controller->getName()])) {
			Log::notice($controller->getName() . ' is already registered.');
			
			return;
		}
		
		Log::info('Registering controller: ' . $controller->getName());
		
		$this->_controllers[$controller->getName()] = $controller;
	}
	

}